﻿#include "opencv.hpp"
#include "xfeatures2d.hpp"
#include "core.hpp"
#include "iostream"
using namespace std;
using namespace cv;


//Harris 角点检测
void MY_Harris(Mat image, string name)
{
	
	//void cv::goodFeaturesToTrack(
	//	cv::InputArray image,    // 输入图像（CV_8UC1 CV_32FC1）
	//	cv::OutputArray corners, // 输出角点vector
	//	int maxCorners,          // 最大角点数目
	//	double qualityLevel,     // 质量水平系数（小于1.0的正数，一般在0.01-0.1之间）
	//	double minDistance,      // 最小距离，小于此距离的点忽略
	//	cv::InputArray mask = noArray(), // mask=0的点忽略
	//	int blockSize = 3,       // 使用的邻域数
	//	bool useHarrisDetector = false,  // false ='Shi Tomasi metric'
	//	double k = 0.04          // Harris角点检测时使用
	//);

	uint64 time = getTickCount();

	std::vector<cv::Point2f> corners;
	for (int i = 0; i < 10; i++)
	{
		goodFeaturesToTrack(image, corners, 100, 0.01, 300, noArray(), 10, true);
	}
	cout << name << "图像大小："<< image.size  << "    Harris 角点检测耗时："<<(getTickCount() - time) / getTickFrequency()/10  << endl;

	//将检测到的角点绘制到原图上
	for (int i = 0; i < corners.size(); i++)
	{
		cv::circle(image, corners[i], 30, cv::Scalar(0, 0, 255), 10, 8, 0);
	}

	namedWindow(name, WINDOW_NORMAL);

	imshow(name, image);

}

void MY_SIFT(string name, Mat image1, Mat image2)
{
	Ptr<Feature2D> sift = xfeatures2d::SIFT::create(100);

	vector<KeyPoint> keypoints_1, keypoints_2;
    Mat descriptors_1, descriptors_2;    

	uint64 time = getTickCount();

	for (int i = 0; i < 10; i++)
	{
		sift->detectAndCompute(image1, noArray(), keypoints_1, descriptors_1);
		sift->detectAndCompute(image2, noArray(), keypoints_2, descriptors_2);
	}
    
	cout <<name<<"图像大小："<< image1.size  <<"   SIFT耗时："<<(getTickCount() - time) / getTickFrequency() / 20 << endl;

	//暴力匹配关键点
	cv::BFMatcher matcher;
	vector<DMatch> matches;
	matcher.match(descriptors_1, descriptors_2, matches);

	Mat out_image;
	drawMatches(image1, keypoints_1, image2, keypoints_2, matches, out_image, Scalar::all(-1), Scalar::all(-1),std::vector<char>(), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

	namedWindow(name + "SIFT"+"匹配结果", WINDOW_NORMAL);
	imshow(name + "SIFT"+"匹配结果", out_image);

	//绘制特征点(关键点)
	//将检测到的角点绘制到原图上
	for (int i = 0; i < keypoints_1.size(); i++)
	{
		cv::circle(image1, keypoints_1[i].pt, 30, cv::Scalar(0, 0, 255), 10, 8, 0);
	}
	for (int i = 0; i < keypoints_2.size(); i++)
	{
		cv::circle(image2, keypoints_2[i].pt, 30, cv::Scalar(0, 0, 255), 10, 8, 0);
	}
	namedWindow(name + "SIFT"+"图片1关键点", WINDOW_NORMAL);
	namedWindow(name + "SIFT"+"图片2关键点", WINDOW_NORMAL);
	imshow(name + "SIFT"+"图片1关键点", image1);
	imshow(name + "SIFT"+"图片2关键点", image2);

}


void MY_SURF(string name, Mat image1, Mat image2)
{
	Ptr<Feature2D> surf = xfeatures2d::SURF::create(15000);

	vector<KeyPoint> keypoints_1, keypoints_2;
    Mat descriptors_1, descriptors_2;    

	uint64 time = getTickCount();

	for (int i = 0; i < 10; i++)
	{
		surf->detectAndCompute(image1, noArray(), keypoints_1, descriptors_1);
		surf->detectAndCompute(image2, noArray(), keypoints_2, descriptors_2);
	}
    
	cout <<name<<"图像大小："<< image1.size  <<"   SURF耗时："<<(getTickCount() - time) / getTickFrequency() / 20 << endl;

	//暴力匹配关键点
	cv::BFMatcher matcher;
	vector<DMatch> matches;
	matcher.match(descriptors_1, descriptors_2, matches);

	Mat out_image;
	drawMatches(image1, keypoints_1, image2, keypoints_2, matches, out_image, Scalar::all(-1), Scalar::all(-1),std::vector<char>(), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

	namedWindow(name + "SURF"+"匹配结果", WINDOW_NORMAL);
	imshow(name + "SURF"+"匹配结果", out_image);

	//绘制特征点(关键点)
	//将检测到的角点绘制到原图上
	for (int i = 0; i < keypoints_1.size(); i++)
	{
		cv::circle(image1, keypoints_1[i].pt, 30, cv::Scalar(0, 0, 255), 10, 8, 0);
	}
	for (int i = 0; i < keypoints_2.size(); i++)
	{
		cv::circle(image2, keypoints_2[i].pt, 30, cv::Scalar(0, 0, 255), 10, 8, 0);
	}
	namedWindow(name + "SURF"+"图片1关键点", WINDOW_NORMAL);
	namedWindow(name + "SURF"+"图片2关键点", WINDOW_NORMAL);
	imshow(name + "SURF"+"图片1关键点", image1);
	imshow(name + "SURF"+"图片2关键点", image2);
}

void MY_ORB(string name, Mat image1, Mat image2)
{
	Ptr<ORB> orb = ORB::create(100);
	vector<KeyPoint> keypoints_1, keypoints_2;
    Mat descriptors_1, descriptors_2;  

	uint64 time = getTickCount();

	for (int i = 0; i < 10; i++)
	{
		orb->detectAndCompute(image1, noArray(), keypoints_1, descriptors_1);
		orb->detectAndCompute(image2, noArray(), keypoints_2, descriptors_2);
	}
	
	cout <<name<<"图像大小："<< image1.size  <<"   ORB耗时："<<(getTickCount() - time) / getTickFrequency() / 20 << endl;	

	//暴力匹配关键点
	cv::BFMatcher matcher;
	vector<DMatch> matches;
	matcher.match(descriptors_1, descriptors_2, matches);

	Mat out_image;
	drawMatches(image1, keypoints_1, image2, keypoints_2, matches, out_image, Scalar::all(-1), Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

	namedWindow(name + "ORB" + "匹配结果", WINDOW_NORMAL);
	imshow(name + "ORB"+"匹配结果", out_image);

	//绘制特征点(关键点)
	//将检测到的角点绘制到原图上
	for (int i = 0; i < keypoints_1.size(); i++)
	{
		cv::circle(image1, keypoints_1[i].pt, 30, cv::Scalar(0, 0, 255), 10, 8, 0);
	}
	for (int i = 0; i < keypoints_2.size(); i++)
	{
		cv::circle(image2, keypoints_2[i].pt, 30, cv::Scalar(0, 0, 255), 10, 8, 0);
	}
	namedWindow(name + "ORB"+"图片1关键点", WINDOW_NORMAL);
	namedWindow(name + "ORB"+"图片2关键点", WINDOW_NORMAL);
	imshow(name + "ORB"+"图片1关键点", image1);
	imshow(name + "ORB"+"图片2关键点", image2);
}


int main()
{
	const char* chessboard = "D:\\opencv class\\chessboard.png";
	const char* picture1 = "D:\\opencv class\\book1.jpg";
	const char* picture2 = "D:\\opencv class\\book2.jpg";

	Mat image_chessboard = imread(chessboard);
	Mat image_picture1 = imread(picture1);
	Mat image_picture2 = imread(picture2);

	Mat gray_chessboard1;
	Mat gray_picture1;
	Mat gray_picture2;
	cvtColor(image_chessboard, gray_chessboard1, COLOR_BGR2GRAY);
	Mat gray_chessboard2 = gray_chessboard1;
	cvtColor(image_picture1, gray_picture1, COLOR_BGR2GRAY);
	cvtColor(image_picture2, gray_picture2, COLOR_BGR2GRAY);

	MY_Harris(gray_chessboard1, "棋盘格");
	MY_Harris(gray_picture1, "图片1");
	MY_Harris(gray_picture2, "图片2");

	MY_SIFT("棋盘格",gray_chessboard1, gray_chessboard2);
	MY_SIFT("书本",  gray_picture1, gray_picture2);

	MY_SURF("棋盘格",gray_chessboard1, gray_chessboard2);
	MY_SURF("书本",  gray_picture1, gray_picture2);

	MY_ORB("棋盘格", gray_chessboard1, gray_chessboard2);
	MY_ORB("书本",   gray_picture1, gray_picture2);

	waitKey(0);

	destroyAllWindows();
}
